home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / program / timecsrc.arc / timecsrc.txt
C/C++ Source or Header  |  1988-10-09  |  9KB  |  240 lines

  1. The following program, timecode, is mainly meant for the programmer crowd.
  2. It lets you time a series of 68000 instructions (entered as short hex numbers)
  3. which of course should constitute valid (and sensible) code; the result is
  4. displayed as a number of clock ticks.
  5.  
  6. The corresponding uuencoded binary and a manual page have been sent to
  7. the moderator of comp.binaries.atari.st.
  8. Compiled with the Lattice C compiler; I used a different startup.bin to
  9. obtain a smaller program (not included).
  10.  
  11. For correspondence conceirning this program (bugs, questions etc.) try
  12.  
  13.       L. J. M. de Wit
  14.       Nachtegaallaan 7
  15.       5731XP Mierlo
  16.       Holland
  17.       e-mail: ..!mcvax!philmds!leo
  18.               (or perhaps  ..!hp4nl!philmds!leo)
  19.  
  20. ------------------------- S t a r t s  h e r e ------------------------------
  21. /******************************************************************************
  22.  *                                                                            *
  23.  *    timecode.c version 1.0 of 27 August 1988   (C) L.J.M. de Wit 1988       *
  24.  *                                                                            *
  25.  * This software may be used and distributed freely if not used commercially  *
  26.  * and the originator (me) is mentioned.                                      *
  27.  *                                                                            *
  28.  ******************************************************************************
  29.  *
  30.  * NAME
  31.  *    timecode - time execution of MC68000 code
  32.  *
  33.  * SYNTAX
  34.  *    timecode [-repeat] <shorthex1> <shorthex2> ...
  35.  *
  36.  * DESCRIPTION
  37.  *    Timecode times the time needed to execute a series of MC68K instructions.
  38.  *    The time taken is expressed in clock ticks.
  39.  *    The repeat flag is optional; it is a number indicating how many times
  40.  *    the series will be repeated (default 100000) so that timing can be
  41.  *    accurate; a lower repeat count will fasten the execution but leads to
  42.  *    less accuracy.
  43.  *
  44.  *    One of the advantages of timecode is that timings can be calculated
  45.  *    online.
  46.  *
  47.  * RESTRICTIONS
  48.  *    1) Up to 32 codes can be timed at once. This is generally no objection,
  49.  *       since most of the time one times only one instruction at a time.
  50.  *    2) When using opcodes that read from or write to memory the pointers
  51.  *       used will have to be prepared correctly. A convenient way is to
  52.  *       time the instruction to load the address register, then time both
  53.  *       the address register load and the instruction that references
  54.  *       memory via that pointer. Subtract the first from the second to
  55.  *       obtain the actual number of ticks for the 'mem-ref' instruction.
  56.  *       This whole story applies to whatever code needs proper
  57.  *       initialization. A safe place for memory references is the screen
  58.  *       memory.
  59.  *    3) Take care when using branches and stuff like jsr, rts etc.
  60.  *       Your code should handle that one way or another.
  61.  *    4) All registers may be used except the stack pointer. SP may be
  62.  *       used if it restored also. The items currently on the stack must
  63.  *       be left undisturbed; if you need to access (SP), first lower SP,
  64.  *       and increment it afterwards.
  65.  */
  66.  
  67. /*
  68.  *    DERIVATION OF TIMING FORMULA.
  69.  *
  70.  *    The formula used for the calculation of the number of ticks is
  71.  *    (using integer division):
  72.  *       ticks = (7791*total + (repeat / 2))/repeat - 32;
  73.  *    where
  74.  *       ticks : # of ticks one execution of the series takes
  75.  *       total : # of milliseconds the complete test takes
  76.  *       repeat: # of repetitions of the series
  77.  *
  78.  *    This has been derived as follows:
  79.  *       total # of effective ticks for the test =
  80.  *       (total - call) * eff * 8000 =
  81.  *       repeat * (ticks + extra)
  82.  *    where
  83.  *       call  : # of milliseconds lost by calling the test function
  84.  *               and saving registers. This is negligable.
  85.  *       eff   : a coefficient (max. 1) that indicates how many ticks of
  86.  *               the processor are really used - the others are lost in
  87.  *               interrupt handling. Measuring gave 0.9739 as value; if the
  88.  *               vbl semaphore was set it increased to 0.9863. The former
  89.  *               value has been used.
  90.  *       extra : # of ticks needed to handle each repetition.
  91.  *               For this program its value is 32.
  92.  *    The 8000 is in fact due to the processor's clock frequency (8Mhz);
  93.  *    a factor 1000 can be found in the number total, which is expressed
  94.  *    in milliseconds instead of seconds.
  95.  *    Filling in eff and extra and adding (repeat / 2) to the nominator
  96.  *    to achieve rounding of the integer division rather than truncating
  97.  *    yields the formula used.
  98.  */
  99.  
  100. /* Because stdio and memory allocation were not needed, the module was
  101.  * linked with a different startup.bin that does not load unnecessary code.
  102.  * In this way the program size has decreased from 12666 to 3391.
  103.  */
  104.  
  105. #include <osbind.h>
  106. #include <portab.h>
  107.  
  108. #define MAXARGC 32                     /* max # of codes */
  109. #define DEF_REPEATS 100000             /* default # of repetitions */
  110. #define HZ_200 (*(ulong *)0x4ba)       /* current 200 Hz clock value */
  111.  
  112. typedef unsigned long ulong;
  113.  
  114. static ulong do_run(), mtime();
  115. static short hexnum();
  116. static void prdec();
  117. static void err_exit();
  118.  
  119. int main(argc,argv)
  120. int argc;
  121. char **argv;
  122. {
  123.    ulong total,                        /* total time for test in millisec. */
  124.          repeat = DEF_REPEATS,         /* # of repetitions */
  125.          ticks;                        /* ticks per repetition for code */
  126.    int i;
  127.  
  128.    i = 1;
  129.    if ((argc > 1) && (argv[1][0] == '-')) {
  130.       i++; repeat = atol(argv[1] + 1);
  131.    }
  132.    total = do_run(argc - i, argv + i,repeat);
  133.    ticks = (7791*total + (repeat / 2))/repeat - 32;
  134.    prdec(ticks); Cconws(" ticks\r\n");
  135.    Pterm0();
  136. }
  137.  
  138. static ulong do_run(argc,argv,repeat)  /* do the test */
  139. int argc;                              /* # of codes */
  140. char **argv;                           /* argv contains codes as strings */
  141. long repeat;                           /* # of repetitions */
  142. {
  143.    int i;
  144.    ulong millitime;                    /* both clock and delta-time */
  145.    short code[MAXARGC + 10],           /* will contain function to be timed */
  146.          *cptr;                        /* pointer into code */
  147.  
  148.    if (argc > MAXARGC) {
  149.       err_exit("too many codes",(char *)0);
  150.    }
  151.    cptr = code;
  152.    *cptr++ = 0x48e7;                   /* movem.l  d0-d7/a0-a6,-(sp) */
  153.    *cptr++ = 0xfffe;                   /* ** save regs */
  154.    *cptr++ = 0x2f2f;                   /* move.l   64(sp),-(sp) */
  155.    *cptr++ = 0x0040;                   /* ** push copy of repeat count */
  156.    for (i = 0; i < argc; i++) {        /* ** now enter all codes supplied */
  157.       *cptr++ = hexnum(argv[i]);
  158.    }
  159.    *cptr++ = 0x5397;                   /* subq.l   #1,(sp)   ** decr repeat */
  160.    *cptr++ = 0x66fc - 2 * argc;        /* bne.s    again  ** jump back */
  161.    *cptr++ = 0x588f;                   /* addq.l   #4,sp  ** pop repeat */
  162.    *cptr++ = 0x4cdf;                   /* movem.l  (sp)+,d0-d7/a0-a6 */
  163.    *cptr++ = 0x7fff;                   /* ** restore regs */
  164.    *cptr++ = 0x4e75;                   /* rts   ** return; timing done */
  165.    millitime = mtime();                /* save current time */
  166.    (*(void (*)())code)(repeat);        /* execute the code just build */
  167.    return mtime() - millitime;         /* return clock difference in msec */
  168. }
  169.  
  170. static short hexnum(str)               /* return the value of str as hex num */
  171. char *str;
  172. {
  173.    short retval = 0;
  174.    short c;
  175.    char *s;
  176.    int i;
  177.  
  178.    for (s = str, i = 0 ; *s != '\0'; i++) {
  179.       if (i == 4) {                    /* max is 4 hex digits */
  180.          err_exit("invalid hex number",str);
  181.       }
  182.       c = *s++;
  183.       if ((c > '9') && (c < 'A')) {
  184.          err_exit("invalid hex number",str);
  185.       }
  186.       if ((c >= 'a') && (c <= 'z')) {
  187.          c += 'A' - 'a';
  188.       }
  189.       if (c >= 'A') {
  190.          c -= 7;
  191.       }
  192.       c -= '0';
  193.       if ((c < 0) || (c > 15)) {
  194.          err_exit("invalid hex number",str);
  195.       }
  196.       retval = (retval << 4) + c;
  197.    }
  198.    return retval;
  199. }
  200.  
  201. static void prdec(num)                 /* print a ulong in de